# @Time : 2024/10/26 23:00
# @Author : Fioman 
# @Phone : 13149920693
"""
__new__: 是一个属于类的类似类方法,第一个参数是cls,作用是创建一个类的实例并且返回.只有在__new__中成功
                创建了 一个实例,并且返回以后,才会调用__init__方法.如不不重写,会调用父类的__new__来创建实例
__init__:  初始化方法或者构造方法,不创建实例,负责初始化赋值__new__()函数创建的实例对象,调用时机是
                __new__创建了实例对象之后并且返回后.
"""


class Simple:
    def __new__(cls, *args, **kwargs):
        print("__new__被调用: {}".format(cls))
        super().__new__(cls)  # 调用父类创建了实例,但是没有返回,不会调用__init__()

    def __init__(self, name):
        self.name = name
        print("__init__被调用: {}".format(self.name))


simple = Simple("Fioman")  # 只打印了__new__被调用


class Simple2:
    def __new__(cls, *args, **kwargs):
        print("__new__2被调用: {}".format(cls))
        return super().__new__(cls)  # 调用父类创建了实例,并且返回了__init__会被调用

    def __init__(self, name):
        self.name = name
        print("__init__2被调用: {}".format(self.name))


simple2 = Simple2("Fioman2")

"""
大多数情况下,我们不需要重写__new__()方法,只有在我们需要自定义类的创建行为的时候才需要重写__new__
方法,比如实现单例模式
"""


class Singleton:
    _instance = None
    _initFlag = False

    def __new__(cls, *args, **kwargs):
        if cls._instance is None:
            print("in __new__ 创建新对象")
            cls._instance = super().__new__(cls)
            return cls._instance
        else:
            return cls._instance

    def __init__(self, name):
        if not self._initFlag:
            print("in __init__() 对象初始化")
            self.name = name
            self._initFlag = True


s1 = Singleton("Fioman")
s2 = Singleton("Fioman2")
s3 = Singleton("Fioman2")
print(s1 is s2)
print(s1 is s3)


# region  实现不可变的类型,初始化放到__new__方法中
class ImmutablePoint:
    def __new__(cls, x, y):
        instance = super().__new__(cls)
        instance._x = x
        instance._y = y
        return instance

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._y


point = ImmutablePoint(1, 2)
print(point.x, point.y)
# point.x = 3  为x和y赋值的时候就会报错
# point.y = 4  因为只有@property属性,没有name.setter属性,就是只读属性
# 如果给其赋值就会报错
point._x = 3  # 但是可以设置_x和_y
point._y = 4
print(point.x, point.y)


# endregion

# region 改变实例化行为,比如元类编程
class Meta(type):
    def __new__(cls, name, bases, classDict):
        print("创建类 {}".format(name))
        return super().__new__(cls, name, bases, classDict)


class MyClass(metaclass=Meta):
    pass

# endregion
